/**
 * @file bull_hal_sys_timer.c
 * @brief 
 * @author yejing (yejh@gongniu.cn)
 * @version 1.0
 * @date 2024-05-16
 * 
 * Copyright 2024-2025 GongNiu Inc. All Rights Reserved.
 * 
 */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "esp_timer.h"

#include "bull_hal_sys_timer.h"
#include "bull_hal_sys_system.h"

/**
 * @brief 创建一个系统定时器
 * 
 * @param timername 定时器的名称，用于标识和区分不同的定时器
 * @param period_msecond 定时器的周期，单位为毫秒
 * @param autoreload 定时器是否自动重载，true表示自动重载，false表示不自动重载
 * @param pvtimerid 定时器的私有ID，可以用于用户定义的标识
 * @param timeout_cb 定时器超时回调函数
 * @return TIMER_HANDLE 返回定时器的句柄，用于后续对定时器的操作
 */
TIMER_HANDLE bull_hal_sys_timer_create( const char *timername, const int period_msecond, const bool_t autoreload, TIMER_ID pvtimerid, TimerCallBack timeout_cb )
{
    return xTimerCreate( timername,
                        period_msecond / portTICK_PERIOD_MS,
                        ( autoreload == true )?pdTRUE:pdFALSE,
                        (void*)pvtimerid,
                        (TimerCallbackFunction_t )timeout_cb);

}
/**
 * @brief 启动定时器
 * 
 * 该函数用于启动一个定时器。如果当前不在中断服务程序中，它将直接通过任务模式启动定时器；
 * 如果当前处于中断服务程序中，它将通过中断模式启动定时器，并在需要时触发任务调度器。
 * 
 * @param timer_handle 定时器的句柄，用于标识和操作具体的定时器实例。
 * @param mSecondToWait 启动定时器后，等待的时间长度（毫秒为单位）。
 * @return 无返回值。
 */
void bull_hal_sys_timer_start( TIMER_HANDLE timer_handle, int mSecondToWait )
{
    if (false == bull_hal_sys_is_in_isr()){
        xTimerStart(timer_handle, mSecondToWait / portTICK_PERIOD_MS);
    }else {
        signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        xTimerStartFromISR(timer_handle, &xHigherPriorityTaskWoken);
        
        if (xHigherPriorityTaskWoken == pdTRUE) {
            taskYIELD();
        }
    }
}


/**
 * @brief 停止定时器
 * @param  timer_handle 定时器的句柄，用于标识和操作具体的定时器实例。
 * @param  mSecondToWait    停止定时器，需要等待时间
 * @return VOID 
 */
void bull_hal_sys_timer_stop( TIMER_HANDLE timer_handle, int mSecondToWait )
{
    if (false == bull_hal_sys_is_in_isr())
        xTimerStop(timer_handle, mSecondToWait / portTICK_PERIOD_MS);
    else {
        signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        xTimerStopFromISR(timer_handle, &xHigherPriorityTaskWoken);
        if (xHigherPriorityTaskWoken == pdTRUE) {
            taskYIELD();
        }
    }
}


/**
 * @brief 重置系统计时器
 * 
 * 该函数用于重置系统的计时器，并等待指定的时间长度。
 * 
 * @param timer_handle 计时器的句柄，用于标识具体的计时器实例。
 * @param mSecondToWait 指定的等待时间，单位为毫秒。
 */
void bull_hal_sys_timer_reset( TIMER_HANDLE timer_handle, int mSecondToWait )
{
    if (false == bull_hal_sys_is_in_isr())
        xTimerReset(timer_handle, mSecondToWait / portTICK_PERIOD_MS);
    else {
        signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        xTimerResetFromISR(timer_handle, &xHigherPriorityTaskWoken);
        if (xHigherPriorityTaskWoken == pdTRUE) {
            taskYIELD();
        }
    }
}

/**
 * @brief 更改系统计时器的周期
 * 
 * 本函数用于修改指定计时器的周期，并可设置等待时间，以便于实现定时器的动态调整。
 * 
 * @param timer_handle 计时器的句柄，用于标识和操作具体的计时器实例。
 * @param mSecondNewPeriod 指定新的计时器周期，单位为毫秒。
 * @param mSecondToWait 指定函数返回前需要等待的时间，单位为毫秒。这允许调用者在修改周期后，
 *                      等待一段时间以确保计时器按照新的周期运行。
 */
void bull_hal_sys_timer_changePeriod( TIMER_HANDLE timer_handle, int mSecondNewPeriod, int mSecondToWait )
{
    if (false == bull_hal_sys_is_in_isr()){
        xTimerChangePeriod(timer_handle, mSecondNewPeriod / portTICK_PERIOD_MS, mSecondToWait / portTICK_PERIOD_MS);
    }else {
        signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        xTimerChangePeriodFromISR(timer_handle, mSecondNewPeriod / portTICK_PERIOD_MS, &xHigherPriorityTaskWoken);
        if (xHigherPriorityTaskWoken == pdTRUE) {
            taskYIELD();
        }
    }
}

/**
 * @brief 删除系统定时器
 * 
 * 该函数用于删除FreeRTOS中的一个定时器。如果定时器正在运行，它会尝试停止定时器并删除它。
 * 
 * @param timer_handle 定时器的句柄，用于标识要删除的定时器。
 * @param mSecondToWait 删除操作等待的超时时间（毫秒）。如果定时器正在执行，这个参数指定了等待其完成的时间。
 */
void bull_hal_sys_timer_delete( TIMER_HANDLE timer_handle, int mSecondToWait )
{
    xTimerDelete( timer_handle, mSecondToWait / portTICK_PERIOD_MS );
}


/**
 * 检查指定的系统计时器是否处于活动状态。
 * 
 * @param timer_handle 计时器的句柄，用于标识特定的计时器实例。
 * @return 返回计时器的活动状态。如果计时器处于活动状态，则返回TRUE；否则返回FALSE。
 */
bool_t bull_hal_sys_timer_isActive( TIMER_HANDLE timer_handle )
{
    return (xTimerIsTimerActive( timer_handle) == pdTRUE)?true:false;
}

/**
 * @brief 分配给被查询的定时器的 ID。
 * 
 * @param timer_handle xTimer  	被查询的定时器。
 * @return void* 
 */
void *bull_hal_sys_pvTimerGetTimerID( TIMER_HANDLE timer_handle )
{
    return pvTimerGetTimerID( timer_handle );
}

/**
 * @brief 创建定时器时，会为软件定时器分配一个标识符 (ID)， 您可随时使用 vTimerSetTimerID() API 函数更改此标识符。
 * 
 * @param timer_handle 
 * @param pvNewID 
 */
void bull_hal_sys_vTimerSetTimerID( TIMER_HANDLE timer_handle, void *pvNewID )
{
    vTimerSetTimerID( timer_handle, pvNewID );
}


